home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 15 / CU Amiga Magazine's Super CD-ROM 15 (1997)(EMAP Images)(GB)[!][issue 1997-10].iso / CUCD / Graphics / Ghostscript / source / istack.h < prev    next >
C/C++ Source or Header  |  1997-04-22  |  10KB  |  231 lines

  1. /* Copyright (C) 1992, 1995 Aladdin Enterprises.  All rights reserved.
  2.   
  3.   This file is part of Aladdin Ghostscript.
  4.   
  5.   Aladdin Ghostscript is distributed with NO WARRANTY OF ANY KIND.  No author
  6.   or distributor accepts any responsibility for the consequences of using it,
  7.   or for whether it serves any particular purpose or works at all, unless he
  8.   or she says so in writing.  Refer to the Aladdin Ghostscript Free Public
  9.   License (the "License") for full details.
  10.   
  11.   Every copy of Aladdin Ghostscript must include a copy of the License,
  12.   normally in a plain ASCII text file named PUBLIC.  The License grants you
  13.   the right to copy, modify and redistribute Aladdin Ghostscript, but only
  14.   under certain conditions described in the License.  Among other things, the
  15.   License requires that the copyright notice and this notice be preserved on
  16.   all copies.
  17. */
  18.  
  19. /* istack.h */
  20. /* Definitions for expandable Ghostscript stacks */
  21. /* Requires iref.h */
  22.  
  23. #ifndef istack_INCLUDED
  24. #  define istack_INCLUDED
  25.  
  26. /* Define an opaque allocator type. */
  27. #ifndef gs_ref_memory_DEFINED
  28. #  define gs_ref_memory_DEFINED
  29. typedef struct gs_ref_memory_s gs_ref_memory_t;
  30. #endif
  31.  
  32. /*
  33.  * The 3 principal Ghostscript stacks (operand, execution, and dictionary)
  34.  * are implemented as a linked list of blocks.  On segmented MS-DOS and
  35.  * MS Windows systems, where there is a substantial performance advantage
  36.  * to keeping the top of the stack in the primary data segment, the top
  37.  * block is stored there, and copied to and from blocks in the heap;
  38.  * on systems with flat address spaces, the top block is stored in the heap
  39.  * like other blocks.  Note that in environments with multiple PostScript
  40.  * contexts, the MS-DOS approach requires some combination of keeping
  41.  * multiple top blocks in the primary data segment, and copying top blocks
  42.  * to and from the heap when switching contexts.
  43.  *
  44.  * Since all operators exit cleanly in case of stack under- or overflow,
  45.  * we handle all issues related to stack blocks in the top-level error
  46.  * recovery code in interp.c.  A few situations require special treatment:
  47.  * see ostack.h, estack.h, and dstack.h for details.
  48.  */
  49.  
  50. #define stacks_are_segmented arch_ptrs_are_segmented
  51. #if stacks_are_segmented
  52. #  define flat_guard(n) 0
  53. #  define segmented_guard(n) (n)
  54. #else
  55. #  define flat_guard(n) (n)
  56. #  define segmented_guard(n) 0
  57. #endif
  58.  
  59. typedef ref _ds *s_ptr;
  60. typedef const ref _ds *const_s_ptr;
  61.  
  62. /*
  63.  * Define the structure for a stack block.
  64.  * In order to simplify allocation, stack blocks are implemented as
  65.  * t_array objects, with the first few elements used for special purposes.
  66.  * The actual layout is as follows:
  67.  *        ref_stack_block structure
  68.  *        bottom guard if any (see below)
  69.  *        used elements of block
  70.  *        unused elements of block
  71.  *        top guard if any (see below)
  72.  * The `next' member of the next higher stack block includes all of this.
  73.  * The `used' member only includes the used elements of this block.
  74.  * Notes:
  75.  *    - In the top block, the size of the `used' member may not be correct.
  76.  *    - In all blocks but the top, we fill the unused elements with nulls.
  77.  */
  78. typedef struct ref_stack_block_s {
  79.     ref next;        /* t_array, next lower block on stack */
  80.     ref used;        /* t_array, subinterval of this block */
  81.         /* Actual stack starts here */
  82. } ref_stack_block;
  83. #define stack_block_refs (sizeof(ref_stack_block) / sizeof(ref))
  84.  
  85. /*
  86.  * In order to detect under- and overflow with minimum overhead, we may put
  87.  * guard elements at the top and bottom of the stacks (see dstack.h,
  88.  * estack.h, and ostack.h for details of the individual stacks).
  89.  * On segmented systems, we only put guard elements around the top block;
  90.  * on other systems, we put guard elements around every block.  Note that
  91.  * in the latter case, the 'current' and  'next' arrays include the
  92.  * guard elements.
  93.  */
  94.  
  95. /*
  96.  * The garbage collector requires that the entire contents of every block
  97.  * be 'clean', i.e., contain legitimate refs; we also need to ensure that
  98.  * at GC time, pointers in unused areas of a block will not be followed
  99.  * (since they may be dangling).  We ensure this as follows:
  100.  *    - When allocating a new block, we set the entire body to nulls.
  101.  *    This is necessary because the block may be freed before the next GC,
  102.  *    and the GC must be able to scan (parse) refs even if they are free.
  103.  *    - When adding a new block to the top of the stack, we set to nulls
  104.  *    the unused area of the new next-to-top blocks.
  105.  *    - At the beginning of garbage collection, we set to nulls the unused
  106.  *    elements of the top block.
  107.  */
  108.  
  109. /*
  110.  * Define the (statically allocated) state of a stack.
  111.  * Note that the total size of a stack cannot exceed max_uint,
  112.  * because it has to be possible to copy a stack to a PostScript array.
  113.  */
  114. #ifndef ref_stack_DEFINED
  115. typedef struct ref_stack_s ref_stack;    /* also defined in idebug.h */
  116. #  define ref_stack_DEFINED
  117. #endif
  118. struct ref_stack_s {
  119.         /* Following are updated dynamically. */
  120.     s_ptr p;            /* current top element */
  121.         /* Following are updated when adding or deleting blocks. */
  122.     s_ptr bot;            /* bottommost valid element */
  123.     s_ptr top;            /* topmost valid element */
  124.     ref current;            /* t_array for current top block */
  125.     uint extension_size;        /* total sizes of extn. blocks */
  126.     uint extension_used;        /* total used sizes of extn. blocks */
  127.         /* Following are updated rarely. */
  128.     ref max_stack;            /* t_integer, Max...Stack user param */
  129.     uint requested;            /* amount of last failing */
  130.                     /* push or pop request */
  131.         /* Following are set at initialization. */
  132.     uint bot_guard;            /* # of guard elements below bot */
  133.     uint top_guard;            /* # of guard elements above top */
  134.     uint block_size;        /* size of each block */
  135.     uint body_size;            /* # of data slots in each block */
  136.     ref guard_value;        /* t__invalid or t_operator, */
  137.                     /* bottom guard value */
  138.     int underflow_error;        /* error code for underflow */
  139.     int overflow_error;        /* error code for overflow */
  140.     bool allow_expansion;        /* if false, don't expand */
  141.     gs_ref_memory_t *memory;    /* allocator for blocks */
  142. };
  143. #define public_st_ref_stack()    /* in istack.c */\
  144.   gs_public_st_complex_only(st_ref_stack, ref_stack, "ref_stack",\
  145.     ref_stack_clear_marks, ref_stack_enum_ptrs, ref_stack_reloc_ptrs, 0)
  146. #define st_ref_stack_num_ptrs 1    /* current */
  147.  
  148. /*
  149.  * Define the loop control for enumerating the elements of a stack,
  150.  * as follows:
  151.  
  152.     STACK_LOOP_BEGIN(pstack, ptr, size)
  153.     ...
  154.     STACK_LOOP_END(ptr, size)
  155.  
  156.  * Each time through the loop, we set ptr to the bottom of a block
  157.  * and size to the size of the block.
  158.  */
  159. #define STACK_LOOP_BEGIN(pstack, ptr, size)\
  160. { ref_stack_block *pblock_ = (ref_stack_block *)(pstack)->current.value.refs;\
  161.   ref *ptr = (pstack)->bot; uint size = (pstack)->p + 1 - (pstack)->bot;\
  162.   for ( ; ; ) {
  163. #define STACK_LOOP_END(ptr, size)\
  164.     pblock_ = (ref_stack_block *)pblock_->next.value.refs;\
  165.     if ( pblock_ == 0 ) break;\
  166.     ptr = pblock_->used.value.refs; size = r_size(&pblock_->used);\
  167.   }\
  168. }
  169.  
  170. /* ------ Procedural interface ------ */
  171.  
  172. /* Initialize a stack.  Note that on segmented systems, */
  173. /* the body of the stack (the elements of the array given by the first ref) */
  174. /* must be in the _ds segment. */
  175. void ref_stack_init(P6(ref_stack *, ref *, uint, uint, ref *,
  176.   gs_ref_memory_t *));
  177.  
  178. /* Set the maximum number of elements allowed on a stack. */
  179. /* Note that the value is a long, not a uint or a ulong. */
  180. int ref_stack_set_max_count(P2(ref_stack *, long));
  181.  
  182. /* Return the number of elements on a stack. */
  183. uint ref_stack_count(P1(const ref_stack *));
  184. #define ref_stack_count_inline(pstk)\
  185.   ((pstk)->p + 1 - (pstk)->bot + (pstk)->extension_used)
  186.  
  187. /* Return the maximum number of elements allowed on a stack. */
  188. #define ref_stack_max_count(pstk) (uint)((pstk)->max_stack.value.intval)
  189.  
  190. /* Return a pointer to a given element from the stack, counting from */
  191. /* 0 as the top element.  If the index is out of range, return 0. */
  192. /* Note that the index is a long, not a uint or a ulong. */
  193. ref *ref_stack_index(P2(const ref_stack *, long));
  194.  
  195. /* Count the number of elements down to and including the first mark. */
  196. /* If no mark is found, return 0. */
  197. uint ref_stack_counttomark(P1(const ref_stack *));
  198.  
  199. /* Store N elements of a stack, starting M elements below the top, */
  200. /*  into an array, with or without store/undo checking. */
  201. /*  age=-1 for no check, 0 for old, 1 for new. */
  202. /* May return e_rangecheck or e_invalidaccess. */
  203. int ref_stack_store(P7(const ref_stack *, ref *, uint, uint, int, bool, client_name_t));
  204.  
  205. /* Pop the top N elements off a stack. */
  206. /* The number must not exceed the number of elements in use. */
  207. void ref_stack_pop(P2(ref_stack *, uint));
  208. #define ref_stack_clear(pstk) ref_stack_pop(pstk, ref_stack_count(pstk))
  209. #define ref_stack_pop_to(pstk, depth)\
  210.   ref_stack_pop(pstk, ref_stack_count(pstk) - (depth))
  211.  
  212. /* Pop the top block off a stack. */
  213. /* May return underflow_error. */
  214. int ref_stack_pop_block(P1(ref_stack *));
  215.  
  216. /* Extend a stack to recover from an overflow condition. */
  217. /* Uses the requested value to decide what to do. */
  218. /* May return overflow_error or e_VMerror. */
  219. int ref_stack_extend(P2(ref_stack *, uint));
  220.  
  221. /* Push N empty slots onto a stack.  These slots are not initialized; */
  222. /* the caller must immediately fill them.  May return overflow_error */
  223. /* (if max_stack would be exceeded, or the stack has no allocator) */
  224. /* or e_VMerror. */
  225. int ref_stack_push(P2(ref_stack *, uint));
  226.  
  227. /* Clean up a stack for garbage collection. */
  228. void ref_stack_cleanup(P1(ref_stack *));
  229.  
  230. #endif                    /* istack_INCLUDED */
  231.